package com.central.dataManage.common.datasourcePlugin;

import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.central.common.model.ColumnInfo;
import com.central.common.model.IndexInfo;
import com.central.dataManage.model.DatabaseInfo;
import com.central.common.model.DatasourceInfo;
import com.central.common.model.TableInfo;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @author Tindy
 * @date 2021/7/5
 * @describe 数据源插件基类
 */
public abstract class BaseDatasourcePlugin {
    public static Logger logger = LoggerFactory.getLogger(BaseDatasourcePlugin.class);

    private DatasourceInfo datasource;
    public BaseDatasourcePlugin(DatasourceInfo datasource){
        this.datasource=datasource;
    }

    public DatasourceInfo getDatasource() {
        return datasource;
    }

    public void setDatasource(DatasourceInfo datasource) {
        this.datasource = datasource;
    }

    /**
     * gets the JDBC url for the data source connection
     *
     * @return
     */
    public abstract String getJdbcUrl();


    /**
     * 获取数据库连接
     * @return
     */
    public abstract Connection getConn() throws SQLException;

    /**
     * 生成其他参数
     * @return
     */
    public String buildOther(String other,String separator){
        StringBuilder otherSb = new StringBuilder();
        if (! StringUtils.isBlank(other)) {
            Map map = JSONObject.parseObject(other, new TypeReference<LinkedHashMap<String, String>>() {
            });
            if (map.size() > 0) {
                Set<String> keys = map.keySet();
                for (String key : keys) {
                    otherSb.append(String.format("%s=%s%s", key, map.get(key), separator));
                }
                otherSb.deleteCharAt(otherSb.length() - 1);
            }
        }
        return otherSb.toString();
    }

    /**
     * 获取数据源数据库信息
     * @param conn
     * @return
     * @throws SQLException
     */
    public abstract List<DatabaseInfo> getDatabases(Connection conn) throws SQLException;

    /**
     * 获取数据源表信息
     * @param database
     * @param conn
     * @return
     * @throws SQLException
     */
    public abstract List<TableInfo> getTables(DatabaseInfo database, Connection conn) throws SQLException;

    /**
     * 获取数据源表字段信息

     * @param database
     * @param table
     * @param conn
     * @return
     * @throws SQLException
     */
    public abstract List<ColumnInfo> getColumns(DatabaseInfo database, TableInfo table, Connection conn) throws SQLException;

    /**
     * 获取数据源表索引信息
     * @param database
     * @param table
     * @param conn
     * @return
     * @throws SQLException
     */
    public abstract List<IndexInfo> getIndexs(DatabaseInfo database, TableInfo table, Connection conn) throws SQLException;

    /**
     * 创建新数据库
     * @param dbName
     */
    public abstract void createNewDatabase(String dbName) throws SQLException;

    /**
     * 删除数据库
     * @param dbName
     */
    public abstract void dropDatabase(String dbName) throws SQLException;

    /**
     * 删除数据表
     * @param dbName
     * @param tableName
     */
    public abstract void dropTable(String dbName, String tableName) throws SQLException;

    /**
     * 检查ddl建表语句语法
     * @param ddl
     */
    public abstract List<SQLStatement> checkCreateTableDdl(String ddl) throws SQLException;

    /**
     * 创建表
     * @param database
     * @param sqlStatements
     * @return
     */
    public abstract void createTableByDdl(DatabaseInfo database, List<SQLStatement> sqlStatements) throws SQLException;

    /**
     * 生成ddl建表语句
     * @param table
     * @returnInfo
     */
    public abstract String generateDdlSql(TableInfo table);

    /**
     * 根据ddl建表语句获取表名
     * @param ddl
     * @return
     */
    public abstract String getTableNameByDdl(String ddl);
    /**
     * 根据ddl修改语句获取表名
     * @param sqlStatement
     * @return
     */
    public abstract String getTableNameByModifyDdl(SQLStatement sqlStatement);

    /**
     * 生成修改表语句
     * @param table
     * @param oldTable
     * @return
     */
    public abstract String generateModifySql(TableInfo table, TableInfo oldTable) throws Exception;

    /**
     * 执行修改表语句
     * @param database
     * @param sqlStatements
     */
    public abstract void modifyTableByDdl(DatabaseInfo database, List<SQLStatement> sqlStatements) throws SQLException;

    /**
     * 检查ddl修改表语句语法
     * @param ddl
     * @param tableName
     * @return
     */
    public abstract List<SQLStatement> checkModifyTableDdl(String ddl,String tableName);

    /**
     * 获取数据类型列表
     * @return
     */
    public abstract List<String> getDataTypes();

    /**
     * 格式化sql
     * @param sql
     * @return
     */
    public  abstract String format(String sql);

    public abstract String getDatasourceDriver();
}
